//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2021 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto/tree/main/CodeGenerator. DO NOT EDIT.

import Foundation
import SotoCore

extension GreengrassV2 {
    // MARK: Enums

    public enum CloudComponentState: String, CustomStringConvertible, Codable {
        case deployable = "DEPLOYABLE"
        case deprecated = "DEPRECATED"
        case failed = "FAILED"
        case initiated = "INITIATED"
        case requested = "REQUESTED"
        public var description: String { return self.rawValue }
    }

    public enum ComponentDependencyType: String, CustomStringConvertible, Codable {
        case hard = "HARD"
        case soft = "SOFT"
        public var description: String { return self.rawValue }
    }

    public enum ComponentVisibilityScope: String, CustomStringConvertible, Codable {
        case `private` = "PRIVATE"
        case `public` = "PUBLIC"
        public var description: String { return self.rawValue }
    }

    public enum CoreDeviceStatus: String, CustomStringConvertible, Codable {
        case healthy = "HEALTHY"
        case unhealthy = "UNHEALTHY"
        public var description: String { return self.rawValue }
    }

    public enum DeploymentComponentUpdatePolicyAction: String, CustomStringConvertible, Codable {
        case notifyComponents = "NOTIFY_COMPONENTS"
        case skipNotifyComponents = "SKIP_NOTIFY_COMPONENTS"
        public var description: String { return self.rawValue }
    }

    public enum DeploymentFailureHandlingPolicy: String, CustomStringConvertible, Codable {
        case doNothing = "DO_NOTHING"
        case rollback = "ROLLBACK"
        public var description: String { return self.rawValue }
    }

    public enum DeploymentHistoryFilter: String, CustomStringConvertible, Codable {
        case all = "ALL"
        case latestOnly = "LATEST_ONLY"
        public var description: String { return self.rawValue }
    }

    public enum DeploymentStatus: String, CustomStringConvertible, Codable {
        case active = "ACTIVE"
        case canceled = "CANCELED"
        case completed = "COMPLETED"
        case failed = "FAILED"
        case inactive = "INACTIVE"
        public var description: String { return self.rawValue }
    }

    public enum EffectiveDeploymentExecutionStatus: String, CustomStringConvertible, Codable {
        case canceled = "CANCELED"
        case completed = "COMPLETED"
        case failed = "FAILED"
        case inProgress = "IN_PROGRESS"
        case queued = "QUEUED"
        case rejected = "REJECTED"
        case timedOut = "TIMED_OUT"
        public var description: String { return self.rawValue }
    }

    public enum InstalledComponentLifecycleState: String, CustomStringConvertible, Codable {
        case broken = "BROKEN"
        case errored = "ERRORED"
        case finished = "FINISHED"
        case installed = "INSTALLED"
        case new = "NEW"
        case running = "RUNNING"
        case starting = "STARTING"
        case stopping = "STOPPING"
        public var description: String { return self.rawValue }
    }

    public enum IoTJobAbortAction: String, CustomStringConvertible, Codable {
        case cancel = "CANCEL"
        public var description: String { return self.rawValue }
    }

    public enum IoTJobExecutionFailureType: String, CustomStringConvertible, Codable {
        case all = "ALL"
        case failed = "FAILED"
        case rejected = "REJECTED"
        case timedOut = "TIMED_OUT"
        public var description: String { return self.rawValue }
    }

    public enum LambdaEventSourceType: String, CustomStringConvertible, Codable {
        case iotCore = "IOT_CORE"
        case pubSub = "PUB_SUB"
        public var description: String { return self.rawValue }
    }

    public enum LambdaFilesystemPermission: String, CustomStringConvertible, Codable {
        case ro
        case rw
        public var description: String { return self.rawValue }
    }

    public enum LambdaInputPayloadEncodingType: String, CustomStringConvertible, Codable {
        case binary
        case json
        public var description: String { return self.rawValue }
    }

    public enum LambdaIsolationMode: String, CustomStringConvertible, Codable {
        case greengrasscontainer = "GreengrassContainer"
        case nocontainer = "NoContainer"
        public var description: String { return self.rawValue }
    }

    public enum RecipeOutputFormat: String, CustomStringConvertible, Codable {
        case json = "JSON"
        case yaml = "YAML"
        public var description: String { return self.rawValue }
    }

    // MARK: Shapes

    public struct CancelDeploymentRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "deploymentId", location: .uri(locationName: "deploymentId"))
        ]

        /// The ID of the deployment.
        public let deploymentId: String

        public init(deploymentId: String) {
            self.deploymentId = deploymentId
        }

        public func validate(name: String) throws {
            try self.validate(self.deploymentId, name: "deploymentId", parent: name, min: 1)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct CancelDeploymentResponse: AWSDecodableShape {
        /// A message that communicates if the cancel was successful.
        public let message: String?

        public init(message: String? = nil) {
            self.message = message
        }

        private enum CodingKeys: String, CodingKey {
            case message
        }
    }

    public struct CloudComponentStatus: AWSDecodableShape {
        /// The state of the component.
        public let componentState: CloudComponentState?
        /// A dictionary of errors that communicate why the component is in an error state. For example, if AWS IoT Greengrass can't access an artifact for the component, then errors contains the artifact's URI as a key, and the error message as the value for that key.
        public let errors: [String: String]?
        /// A message that communicates details, such as errors, about the status of the component.
        public let message: String?

        public init(componentState: CloudComponentState? = nil, errors: [String: String]? = nil, message: String? = nil) {
            self.componentState = componentState
            self.errors = errors
            self.message = message
        }

        private enum CodingKeys: String, CodingKey {
            case componentState
            case errors
            case message
        }
    }

    public struct Component: AWSDecodableShape {
        /// The ARN of the component version.
        public let arn: String?
        /// The name of the component.
        public let componentName: String?
        /// The latest version of the component and its details.
        public let latestVersion: ComponentLatestVersion?

        public init(arn: String? = nil, componentName: String? = nil, latestVersion: ComponentLatestVersion? = nil) {
            self.arn = arn
            self.componentName = componentName
            self.latestVersion = latestVersion
        }

        private enum CodingKeys: String, CodingKey {
            case arn
            case componentName
            case latestVersion
        }
    }

    public struct ComponentCandidate: AWSEncodableShape {
        /// The name of the component.
        public let componentName: String?
        /// The version of the component.
        public let componentVersion: String?
        /// The version requirements for the component's dependencies. AWS IoT Greengrass core devices get the version requirements from component recipes. AWS IoT Greengrass V2 uses semantic version constraints. For more information, see Semantic Versioning.
        public let versionRequirements: [String: String]?

        public init(componentName: String? = nil, componentVersion: String? = nil, versionRequirements: [String: String]? = nil) {
            self.componentName = componentName
            self.componentVersion = componentVersion
            self.versionRequirements = versionRequirements
        }

        public func validate(name: String) throws {
            try self.validate(self.componentName, name: "componentName", parent: name, max: 128)
            try self.validate(self.componentName, name: "componentName", parent: name, min: 1)
            try self.validate(self.componentName, name: "componentName", parent: name, pattern: "[a-zA-Z0-9-_.]+")
            try self.validate(self.componentVersion, name: "componentVersion", parent: name, max: 64)
            try self.validate(self.componentVersion, name: "componentVersion", parent: name, min: 1)
            try self.validate(self.componentVersion, name: "componentVersion", parent: name, pattern: "[0-9a-zA-Z-.+]+")
            try self.versionRequirements?.forEach {
                try validate($0.key, name: "versionRequirements.key", parent: name, min: 1)
                try validate($0.value, name: "versionRequirements[\"\($0.key)\"]", parent: name, min: 1)
            }
        }

        private enum CodingKeys: String, CodingKey {
            case componentName
            case componentVersion
            case versionRequirements
        }
    }

    public struct ComponentConfigurationUpdate: AWSEncodableShape & AWSDecodableShape {
        /// A serialized JSON string that contains the configuration object to merge to target devices. The core device merges this configuration with the component's existing configuration. If this is the first time a component deploys on a device, the core device merges this configuration with the component's default configuration. This means that the core device keeps it's existing configuration for keys and values that you don't specify in this object. For more information, see Merge configuration updates in the AWS IoT Greengrass V2 Developer Guide.
        public let merge: String?
        /// The list of configuration nodes to reset to default values on target devices. Use JSON pointers to specify each node to reset. JSON pointers start with a forward slash (/) and use forward slashes to separate the key for each level in the object. For more information, see the JSON pointer specification and Reset configuration updates in the AWS IoT Greengrass V2 Developer Guide.
        public let reset: [String]?

        public init(merge: String? = nil, reset: [String]? = nil) {
            self.merge = merge
            self.reset = reset
        }

        public func validate(name: String) throws {
            try self.validate(self.merge, name: "merge", parent: name, max: 65536)
            try self.validate(self.merge, name: "merge", parent: name, min: 1)
            try self.reset?.forEach {
                try validate($0, name: "reset[]", parent: name, max: 256)
                try validate($0, name: "reset[]", parent: name, min: 0)
            }
        }

        private enum CodingKeys: String, CodingKey {
            case merge
            case reset
        }
    }

    public struct ComponentDependencyRequirement: AWSEncodableShape {
        /// The type of this dependency. Choose from the following options:    SOFT – The component doesn't restart if the dependency changes state.    HARD – The component restarts if the dependency changes state.   Default: HARD
        public let dependencyType: ComponentDependencyType?
        /// The component version requirement for the component dependency. AWS IoT Greengrass V2 uses semantic version constraints. For more information, see Semantic Versioning.
        public let versionRequirement: String?

        public init(dependencyType: ComponentDependencyType? = nil, versionRequirement: String? = nil) {
            self.dependencyType = dependencyType
            self.versionRequirement = versionRequirement
        }

        public func validate(name: String) throws {
            try self.validate(self.versionRequirement, name: "versionRequirement", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case dependencyType
            case versionRequirement
        }
    }

    public struct ComponentDeploymentSpecification: AWSEncodableShape & AWSDecodableShape {
        /// The version of the component.
        public let componentVersion: String?
        /// The configuration updates to deploy for the component. You can define reset updates and merge updates. A reset updates the keys that you specify to the default configuration for the component. A merge updates the core device's component configuration with the keys and values that you specify. The AWS IoT Greengrass Core software applies reset updates before it applies merge updates. For more information, see Update component configurations in the AWS IoT Greengrass V2 Developer Guide.
        public let configurationUpdate: ComponentConfigurationUpdate?
        /// The system user and group that the AWS IoT Greengrass Core software uses to run component processes on the core device. If you omit this parameter, the AWS IoT Greengrass Core software uses the system user and group that you configure for the core device. For more information, see Configure the user and group that run components in the AWS IoT Greengrass V2 Developer Guide.
        public let runWith: ComponentRunWith?

        public init(componentVersion: String? = nil, configurationUpdate: ComponentConfigurationUpdate? = nil, runWith: ComponentRunWith? = nil) {
            self.componentVersion = componentVersion
            self.configurationUpdate = configurationUpdate
            self.runWith = runWith
        }

        public func validate(name: String) throws {
            try self.validate(self.componentVersion, name: "componentVersion", parent: name, max: 64)
            try self.validate(self.componentVersion, name: "componentVersion", parent: name, min: 1)
            try self.validate(self.componentVersion, name: "componentVersion", parent: name, pattern: "[0-9a-zA-Z-.+]+")
            try self.configurationUpdate?.validate(name: "\(name).configurationUpdate")
            try self.runWith?.validate(name: "\(name).runWith")
        }

        private enum CodingKeys: String, CodingKey {
            case componentVersion
            case configurationUpdate
            case runWith
        }
    }

    public struct ComponentLatestVersion: AWSDecodableShape {
        /// The ARN of the component version.
        public let arn: String?
        /// The version of the component.
        public let componentVersion: String?
        /// The time at which the component was created, expressed in ISO 8601 format.
        public let creationTimestamp: Date?
        /// The description of the component version.
        public let description: String?
        /// The platforms that the component version supports.
        public let platforms: [ComponentPlatform]?
        /// The publisher of the component version.
        public let publisher: String?

        public init(arn: String? = nil, componentVersion: String? = nil, creationTimestamp: Date? = nil, description: String? = nil, platforms: [ComponentPlatform]? = nil, publisher: String? = nil) {
            self.arn = arn
            self.componentVersion = componentVersion
            self.creationTimestamp = creationTimestamp
            self.description = description
            self.platforms = platforms
            self.publisher = publisher
        }

        private enum CodingKeys: String, CodingKey {
            case arn
            case componentVersion
            case creationTimestamp
            case description
            case platforms
            case publisher
        }
    }

    public struct ComponentPlatform: AWSEncodableShape & AWSDecodableShape {
        /// A dictionary of attributes for the platform. The AWS IoT Greengrass Core software defines the os and platform by default. You can specify additional platform attributes for a core device when you deploy the AWS IoT Greengrass nucleus component. For more information, see the AWS IoT Greengrass nucleus component in the AWS IoT Greengrass V2 Developer Guide.
        public let attributes: [String: String]?
        /// The friendly name of the platform. This name helps you identify the platform. If you omit this parameter, AWS IoT Greengrass creates a friendly name from the os and architecture of the platform.
        public let name: String?

        public init(attributes: [String: String]? = nil, name: String? = nil) {
            self.attributes = attributes
            self.name = name
        }

        public func validate(name: String) throws {
            try self.attributes?.forEach {
                try validate($0.key, name: "attributes.key", parent: name, min: 1)
                try validate($0.value, name: "attributes[\"\($0.key)\"]", parent: name, min: 1)
            }
            try self.validate(self.name, name: "name", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case attributes
            case name
        }
    }

    public struct ComponentRunWith: AWSEncodableShape & AWSDecodableShape {
        /// The POSIX system user and (optional) group to use to run this component. Specify the user and group separated by a colon (:) in the following format: user:group. The group is optional. If you don't specify a group, the AWS IoT Greengrass Core software uses the primary user for the group.
        public let posixUser: String?

        public init(posixUser: String? = nil) {
            self.posixUser = posixUser
        }

        public func validate(name: String) throws {
            try self.validate(self.posixUser, name: "posixUser", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case posixUser
        }
    }

    public struct ComponentVersionListItem: AWSDecodableShape {
        /// The ARN of the component version.
        public let arn: String?
        /// The name of the component.
        public let componentName: String?
        /// The version of the component.
        public let componentVersion: String?

        public init(arn: String? = nil, componentName: String? = nil, componentVersion: String? = nil) {
            self.arn = arn
            self.componentName = componentName
            self.componentVersion = componentVersion
        }

        private enum CodingKeys: String, CodingKey {
            case arn
            case componentName
            case componentVersion
        }
    }

    public struct CoreDevice: AWSDecodableShape {
        /// The name of the core device. This is also the name of the AWS IoT thing.
        public let coreDeviceThingName: String?
        /// The time at which the core device's status last updated, expressed in ISO 8601 format.
        public let lastStatusUpdateTimestamp: Date?
        /// The status of the core device. Core devices can have the following statuses:    HEALTHY – The AWS IoT Greengrass Core software and all components run on the core device without issue.    UNHEALTHY – The AWS IoT Greengrass Core software or a component is in a failed state on the core device.
        public let status: CoreDeviceStatus?

        public init(coreDeviceThingName: String? = nil, lastStatusUpdateTimestamp: Date? = nil, status: CoreDeviceStatus? = nil) {
            self.coreDeviceThingName = coreDeviceThingName
            self.lastStatusUpdateTimestamp = lastStatusUpdateTimestamp
            self.status = status
        }

        private enum CodingKeys: String, CodingKey {
            case coreDeviceThingName
            case lastStatusUpdateTimestamp
            case status
        }
    }

    public struct CreateComponentVersionRequest: AWSEncodableShape {
        /// The recipe to use to create the component. The recipe defines the component's metadata, parameters, dependencies, lifecycle, artifacts, and platform compatibility. You must specify either inlineRecipe or lambdaFunction.
        public let inlineRecipe: Data?
        /// The parameters to create a component from a Lambda function. You must specify either inlineRecipe or lambdaFunction.
        public let lambdaFunction: LambdaFunctionRecipeSource?
        /// A list of key-value pairs that contain metadata for the resource. For more information, see Tag your resources in the AWS IoT Greengrass V2 Developer Guide.
        public let tags: [String: String]?

        public init(inlineRecipe: Data? = nil, lambdaFunction: LambdaFunctionRecipeSource? = nil, tags: [String: String]? = nil) {
            self.inlineRecipe = inlineRecipe
            self.lambdaFunction = lambdaFunction
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.lambdaFunction?.validate(name: "\(name).lambdaFunction")
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.key, name: "tags.key", parent: name, pattern: "^(?!aws:)[a-zA-Z+-=._:/]+$")
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
        }

        private enum CodingKeys: String, CodingKey {
            case inlineRecipe
            case lambdaFunction
            case tags
        }
    }

    public struct CreateComponentVersionResponse: AWSDecodableShape {
        /// The ARN of the component version.
        public let arn: String?
        /// The name of the component.
        public let componentName: String
        /// The version of the component.
        public let componentVersion: String
        /// The time at which the component was created, expressed in ISO 8601 format.
        public let creationTimestamp: Date
        /// The status of the component version in AWS IoT Greengrass V2. This status is different from the status of the component on a core device.
        public let status: CloudComponentStatus

        public init(arn: String? = nil, componentName: String, componentVersion: String, creationTimestamp: Date, status: CloudComponentStatus) {
            self.arn = arn
            self.componentName = componentName
            self.componentVersion = componentVersion
            self.creationTimestamp = creationTimestamp
            self.status = status
        }

        private enum CodingKeys: String, CodingKey {
            case arn
            case componentName
            case componentVersion
            case creationTimestamp
            case status
        }
    }

    public struct CreateDeploymentRequest: AWSEncodableShape {
        /// The components to deploy. This is a dictionary, where each key is the name of a component, and each key's value is the version and configuration to deploy for that component.
        public let components: [String: ComponentDeploymentSpecification]?
        /// The name of the deployment. You can create deployments without names. If you create a deployment without a name, the AWS IoT Greengrass V2 console shows the deployment name as &lt;targetType&gt;:&lt;targetName&gt;, where targetType and targetName are the type and name of the deployment target.
        public let deploymentName: String?
        /// The deployment policies for the deployment. These policies define how the deployment updates components and handles failure.
        public let deploymentPolicies: DeploymentPolicies?
        /// The job configuration for the deployment configuration. The job configuration specifies the rollout, timeout, and stop configurations for the deployment configuration.
        public let iotJobConfiguration: DeploymentIoTJobConfiguration?
        /// A list of key-value pairs that contain metadata for the resource. For more information, see Tag your resources in the AWS IoT Greengrass V2 Developer Guide.
        public let tags: [String: String]?
        /// The ARN of the target AWS IoT thing or thing group.
        public let targetArn: String

        public init(components: [String: ComponentDeploymentSpecification]? = nil, deploymentName: String? = nil, deploymentPolicies: DeploymentPolicies? = nil, iotJobConfiguration: DeploymentIoTJobConfiguration? = nil, tags: [String: String]? = nil, targetArn: String) {
            self.components = components
            self.deploymentName = deploymentName
            self.deploymentPolicies = deploymentPolicies
            self.iotJobConfiguration = iotJobConfiguration
            self.tags = tags
            self.targetArn = targetArn
        }

        public func validate(name: String) throws {
            try self.components?.forEach {
                try validate($0.key, name: "components.key", parent: name, min: 1)
                try $0.value.validate(name: "\(name).components[\"\($0.key)\"]")
            }
            try self.validate(self.deploymentName, name: "deploymentName", parent: name, min: 1)
            try self.iotJobConfiguration?.validate(name: "\(name).iotJobConfiguration")
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.key, name: "tags.key", parent: name, pattern: "^(?!aws:)[a-zA-Z+-=._:/]+$")
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.targetArn, name: "targetArn", parent: name, pattern: "arn:aws(-cn|-us-gov)?:iot:[^:]+:[0-9]+:(thing|thinggroup)/.+")
        }

        private enum CodingKeys: String, CodingKey {
            case components
            case deploymentName
            case deploymentPolicies
            case iotJobConfiguration
            case tags
            case targetArn
        }
    }

    public struct CreateDeploymentResponse: AWSDecodableShape {
        /// The ID of the deployment.
        public let deploymentId: String?
        /// The ARN of the AWS IoT job that applies the deployment to target devices.
        public let iotJobArn: String?
        /// The ID of the AWS IoT job that applies the deployment to target devices.
        public let iotJobId: String?

        public init(deploymentId: String? = nil, iotJobArn: String? = nil, iotJobId: String? = nil) {
            self.deploymentId = deploymentId
            self.iotJobArn = iotJobArn
            self.iotJobId = iotJobId
        }

        private enum CodingKeys: String, CodingKey {
            case deploymentId
            case iotJobArn
            case iotJobId
        }
    }

    public struct DeleteComponentRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "arn", location: .uri(locationName: "arn"))
        ]

        /// The ARN of the component version.
        public let arn: String

        public init(arn: String) {
            self.arn = arn
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, pattern: "arn:aws(-cn|-us-gov)?:greengrass:[^:]+:(aws|[0-9]+):components:[^:]+:versions:[^:]+")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct DeleteCoreDeviceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "coreDeviceThingName", location: .uri(locationName: "coreDeviceThingName"))
        ]

        /// The name of the core device. This is also the name of the AWS IoT thing.
        public let coreDeviceThingName: String

        public init(coreDeviceThingName: String) {
            self.coreDeviceThingName = coreDeviceThingName
        }

        public func validate(name: String) throws {
            try self.validate(self.coreDeviceThingName, name: "coreDeviceThingName", parent: name, max: 128)
            try self.validate(self.coreDeviceThingName, name: "coreDeviceThingName", parent: name, min: 1)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct Deployment: AWSDecodableShape {
        /// The time at which the deployment was created, expressed in ISO 8601 format.
        public let creationTimestamp: Date?
        /// The ID of the deployment.
        public let deploymentId: String?
        /// The name of the deployment. You can create deployments without names. If you create a deployment without a name, the AWS IoT Greengrass V2 console shows the deployment name as &lt;targetType&gt;:&lt;targetName&gt;, where targetType and targetName are the type and name of the deployment target.
        public let deploymentName: String?
        /// The status of the deployment.
        public let deploymentStatus: DeploymentStatus?
        /// Whether or not the deployment is the latest revision for its target.
        public let isLatestForTarget: Bool?
        /// The revision number of the deployment.
        public let revisionId: String?
        /// The ARN of the target AWS IoT thing or thing group.
        public let targetArn: String?

        public init(creationTimestamp: Date? = nil, deploymentId: String? = nil, deploymentName: String? = nil, deploymentStatus: DeploymentStatus? = nil, isLatestForTarget: Bool? = nil, revisionId: String? = nil, targetArn: String? = nil) {
            self.creationTimestamp = creationTimestamp
            self.deploymentId = deploymentId
            self.deploymentName = deploymentName
            self.deploymentStatus = deploymentStatus
            self.isLatestForTarget = isLatestForTarget
            self.revisionId = revisionId
            self.targetArn = targetArn
        }

        private enum CodingKeys: String, CodingKey {
            case creationTimestamp
            case deploymentId
            case deploymentName
            case deploymentStatus
            case isLatestForTarget
            case revisionId
            case targetArn
        }
    }

    public struct DeploymentComponentUpdatePolicy: AWSEncodableShape & AWSDecodableShape {
        /// Whether or not to notify components and wait for components to become safe to update. Choose from the following options:    NOTIFY_COMPONENTS – The deployment notifies each component before it stops and updates that component. Components can use the SubscribeToComponentUpdates IPC operation to receive these notifications. Then, components can respond with the DeferComponentUpdate IPC operation. For more information, see Create deployments in the AWS IoT Greengrass V2 Developer Guide.    SKIP_NOTIFY_COMPONENTS – The deployment doesn't notify components or wait for them to be safe to update.   Default: NOTIFY_COMPONENTS
        public let action: DeploymentComponentUpdatePolicyAction?
        /// The amount of time in seconds that each component on a device has to report that it's safe to update. If the component waits for longer than this timeout, then the deployment proceeds on the device. Default: 60
        public let timeoutInSeconds: Int?

        public init(action: DeploymentComponentUpdatePolicyAction? = nil, timeoutInSeconds: Int? = nil) {
            self.action = action
            self.timeoutInSeconds = timeoutInSeconds
        }

        private enum CodingKeys: String, CodingKey {
            case action
            case timeoutInSeconds
        }
    }

    public struct DeploymentConfigurationValidationPolicy: AWSEncodableShape & AWSDecodableShape {
        /// The amount of time in seconds that a component can validate its configuration updates. If the validation time exceeds this timeout, then the deployment proceeds for the device. Default: 30
        public let timeoutInSeconds: Int?

        public init(timeoutInSeconds: Int? = nil) {
            self.timeoutInSeconds = timeoutInSeconds
        }

        private enum CodingKeys: String, CodingKey {
            case timeoutInSeconds
        }
    }

    public struct DeploymentIoTJobConfiguration: AWSEncodableShape & AWSDecodableShape {
        /// The stop configuration for the job. This configuration defines when and how to stop a job rollout.
        public let abortConfig: IoTJobAbortConfig?
        /// The rollout configuration for the job. This configuration defines the rate at which the job rolls out to the fleet of target devices.
        public let jobExecutionsRolloutConfig: IoTJobExecutionsRolloutConfig?
        /// The timeout configuration for the job. This configuration defines the amount of time each device has to complete the job.
        public let timeoutConfig: IoTJobTimeoutConfig?

        public init(abortConfig: IoTJobAbortConfig? = nil, jobExecutionsRolloutConfig: IoTJobExecutionsRolloutConfig? = nil, timeoutConfig: IoTJobTimeoutConfig? = nil) {
            self.abortConfig = abortConfig
            self.jobExecutionsRolloutConfig = jobExecutionsRolloutConfig
            self.timeoutConfig = timeoutConfig
        }

        public func validate(name: String) throws {
            try self.abortConfig?.validate(name: "\(name).abortConfig")
            try self.jobExecutionsRolloutConfig?.validate(name: "\(name).jobExecutionsRolloutConfig")
        }

        private enum CodingKeys: String, CodingKey {
            case abortConfig
            case jobExecutionsRolloutConfig
            case timeoutConfig
        }
    }

    public struct DeploymentPolicies: AWSEncodableShape & AWSDecodableShape {
        /// The component update policy for the configuration deployment. This policy defines when it's safe to deploy the configuration to devices.
        public let componentUpdatePolicy: DeploymentComponentUpdatePolicy?
        /// The configuration validation policy for the configuration deployment. This policy defines how long each component has to validate its configure updates.
        public let configurationValidationPolicy: DeploymentConfigurationValidationPolicy?
        /// The failure handling policy for the configuration deployment. This policy defines what to do if the deployment fails. Default: ROLLBACK
        public let failureHandlingPolicy: DeploymentFailureHandlingPolicy?

        public init(componentUpdatePolicy: DeploymentComponentUpdatePolicy? = nil, configurationValidationPolicy: DeploymentConfigurationValidationPolicy? = nil, failureHandlingPolicy: DeploymentFailureHandlingPolicy? = nil) {
            self.componentUpdatePolicy = componentUpdatePolicy
            self.configurationValidationPolicy = configurationValidationPolicy
            self.failureHandlingPolicy = failureHandlingPolicy
        }

        private enum CodingKeys: String, CodingKey {
            case componentUpdatePolicy
            case configurationValidationPolicy
            case failureHandlingPolicy
        }
    }

    public struct DescribeComponentRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "arn", location: .uri(locationName: "arn"))
        ]

        /// The ARN of the component version.
        public let arn: String

        public init(arn: String) {
            self.arn = arn
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, pattern: "arn:aws(-cn|-us-gov)?:greengrass:[^:]+:(aws|[0-9]+):components:[^:]+:versions:[^:]+")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct DescribeComponentResponse: AWSDecodableShape {
        /// The ARN of the component version.
        public let arn: String?
        /// The name of the component.
        public let componentName: String?
        /// The version of the component.
        public let componentVersion: String?
        /// The time at which the component was created, expressed in ISO 8601 format.
        public let creationTimestamp: Date?
        /// The description of the component version.
        public let description: String?
        /// The platforms that the component version supports.
        public let platforms: [ComponentPlatform]?
        /// The publisher of the component version.
        public let publisher: String?
        /// The status of the component version in AWS IoT Greengrass V2. This status is different from the status of the component on a core device.
        public let status: CloudComponentStatus?
        /// A list of key-value pairs that contain metadata for the resource. For more information, see Tag your resources in the AWS IoT Greengrass V2 Developer Guide.
        public let tags: [String: String]?

        public init(arn: String? = nil, componentName: String? = nil, componentVersion: String? = nil, creationTimestamp: Date? = nil, description: String? = nil, platforms: [ComponentPlatform]? = nil, publisher: String? = nil, status: CloudComponentStatus? = nil, tags: [String: String]? = nil) {
            self.arn = arn
            self.componentName = componentName
            self.componentVersion = componentVersion
            self.creationTimestamp = creationTimestamp
            self.description = description
            self.platforms = platforms
            self.publisher = publisher
            self.status = status
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case arn
            case componentName
            case componentVersion
            case creationTimestamp
            case description
            case platforms
            case publisher
            case status
            case tags
        }
    }

    public struct EffectiveDeployment: AWSDecodableShape {
        /// The status of the deployment job on the AWS IoT Greengrass core device.
        public let coreDeviceExecutionStatus: EffectiveDeploymentExecutionStatus
        /// The time at which the deployment was created, expressed in ISO 8601 format.
        public let creationTimestamp: Date
        /// The ID of the deployment.
        public let deploymentId: String
        /// The name of the deployment. You can create deployments without names. If you create a deployment without a name, the AWS IoT Greengrass V2 console shows the deployment name as &lt;targetType&gt;:&lt;targetName&gt;, where targetType and targetName are the type and name of the deployment target.
        public let deploymentName: String
        /// The description of the deployment job.
        public let description: String?
        /// The ARN of the AWS IoT job that applies the deployment to target devices.
        public let iotJobArn: String?
        /// The ID of the AWS IoT job that applies the deployment to target devices.
        public let iotJobId: String?
        /// The time at which the deployment job was last modified, expressed in ISO 8601 format.
        public let modifiedTimestamp: Date
        /// The reason code for the update, if the job was updated.
        public let reason: String?
        /// The ARN of the target AWS IoT thing or thing group.
        public let targetArn: String

        public init(coreDeviceExecutionStatus: EffectiveDeploymentExecutionStatus, creationTimestamp: Date, deploymentId: String, deploymentName: String, description: String? = nil, iotJobArn: String? = nil, iotJobId: String? = nil, modifiedTimestamp: Date, reason: String? = nil, targetArn: String) {
            self.coreDeviceExecutionStatus = coreDeviceExecutionStatus
            self.creationTimestamp = creationTimestamp
            self.deploymentId = deploymentId
            self.deploymentName = deploymentName
            self.description = description
            self.iotJobArn = iotJobArn
            self.iotJobId = iotJobId
            self.modifiedTimestamp = modifiedTimestamp
            self.reason = reason
            self.targetArn = targetArn
        }

        private enum CodingKeys: String, CodingKey {
            case coreDeviceExecutionStatus
            case creationTimestamp
            case deploymentId
            case deploymentName
            case description
            case iotJobArn
            case iotJobId
            case modifiedTimestamp
            case reason
            case targetArn
        }
    }

    public struct GetComponentRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "arn", location: .uri(locationName: "arn")),
            AWSMemberEncoding(label: "recipeOutputFormat", location: .querystring(locationName: "recipeOutputFormat"))
        ]

        /// The ARN of the component version.
        public let arn: String
        /// The format of the recipe.
        public let recipeOutputFormat: RecipeOutputFormat?

        public init(arn: String, recipeOutputFormat: RecipeOutputFormat? = nil) {
            self.arn = arn
            self.recipeOutputFormat = recipeOutputFormat
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, pattern: "arn:aws(-cn|-us-gov)?:greengrass:[^:]+:(aws|[0-9]+):components:[^:]+:versions:[^:]+")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetComponentResponse: AWSDecodableShape {
        /// The recipe of the component version.
        public let recipe: Data
        /// The format of the recipe.
        public let recipeOutputFormat: RecipeOutputFormat
        /// A list of key-value pairs that contain metadata for the resource. For more information, see Tag your resources in the AWS IoT Greengrass V2 Developer Guide.
        public let tags: [String: String]?

        public init(recipe: Data, recipeOutputFormat: RecipeOutputFormat, tags: [String: String]? = nil) {
            self.recipe = recipe
            self.recipeOutputFormat = recipeOutputFormat
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case recipe
            case recipeOutputFormat
            case tags
        }
    }

    public struct GetComponentVersionArtifactRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "arn", location: .uri(locationName: "arn")),
            AWSMemberEncoding(label: "artifactName", location: .uri(locationName: "artifactName"))
        ]

        /// The ARN of the component version. Specify the ARN of a public component version.
        public let arn: String
        /// The name of the artifact. You can use the GetComponent operation to download the component recipe, which includes the URI of the artifact. The artifact name is the section of the URI after the scheme. For example, in the artifact URI greengrass:SomeArtifact.zip, the artifact name is SomeArtifact.zip.
        public let artifactName: String

        public init(arn: String, artifactName: String) {
            self.arn = arn
            self.artifactName = artifactName
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, pattern: "arn:aws(-cn|-us-gov)?:greengrass:[^:]+:(aws|[0-9]+):components:[^:]+:versions:[^:]+")
            try self.validate(self.artifactName, name: "artifactName", parent: name, min: 1)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetComponentVersionArtifactResponse: AWSDecodableShape {
        /// The URL of the artifact.
        public let preSignedUrl: String

        public init(preSignedUrl: String) {
            self.preSignedUrl = preSignedUrl
        }

        private enum CodingKeys: String, CodingKey {
            case preSignedUrl
        }
    }

    public struct GetCoreDeviceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "coreDeviceThingName", location: .uri(locationName: "coreDeviceThingName"))
        ]

        /// The name of the core device. This is also the name of the AWS IoT thing.
        public let coreDeviceThingName: String

        public init(coreDeviceThingName: String) {
            self.coreDeviceThingName = coreDeviceThingName
        }

        public func validate(name: String) throws {
            try self.validate(self.coreDeviceThingName, name: "coreDeviceThingName", parent: name, max: 128)
            try self.validate(self.coreDeviceThingName, name: "coreDeviceThingName", parent: name, min: 1)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetCoreDeviceResponse: AWSDecodableShape {
        /// The computer architecture of the core device.
        public let architecture: String?
        /// The name of the core device. This is also the name of the AWS IoT thing.
        public let coreDeviceThingName: String?
        /// The version of the AWS IoT Greengrass Core software that the core device runs. This version is equivalent to the version of the AWS IoT Greengrass nucleus component that runs on the core device. For more information, see the AWS IoT Greengrass nucleus component in the AWS IoT Greengrass V2 Developer Guide.
        public let coreVersion: String?
        /// The time at which the core device's status last updated, expressed in ISO 8601 format.
        public let lastStatusUpdateTimestamp: Date?
        /// The operating system platform that the core device runs.
        public let platform: String?
        /// The status of the core device. The core device status can be:    HEALTHY – The AWS IoT Greengrass Core software and all components run on the core device without issue.    UNHEALTHY – The AWS IoT Greengrass Core software or a component is in a failed state on the core device.
        public let status: CoreDeviceStatus?
        /// A list of key-value pairs that contain metadata for the resource. For more information, see Tag your resources in the AWS IoT Greengrass V2 Developer Guide.
        public let tags: [String: String]?

        public init(architecture: String? = nil, coreDeviceThingName: String? = nil, coreVersion: String? = nil, lastStatusUpdateTimestamp: Date? = nil, platform: String? = nil, status: CoreDeviceStatus? = nil, tags: [String: String]? = nil) {
            self.architecture = architecture
            self.coreDeviceThingName = coreDeviceThingName
            self.coreVersion = coreVersion
            self.lastStatusUpdateTimestamp = lastStatusUpdateTimestamp
            self.platform = platform
            self.status = status
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case architecture
            case coreDeviceThingName
            case coreVersion
            case lastStatusUpdateTimestamp
            case platform
            case status
            case tags
        }
    }

    public struct GetDeploymentRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "deploymentId", location: .uri(locationName: "deploymentId"))
        ]

        /// The ID of the deployment.
        public let deploymentId: String

        public init(deploymentId: String) {
            self.deploymentId = deploymentId
        }

        public func validate(name: String) throws {
            try self.validate(self.deploymentId, name: "deploymentId", parent: name, min: 1)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetDeploymentResponse: AWSDecodableShape {
        /// The components to deploy. This is a dictionary, where each key is the name of a component, and each key's value is the version and configuration to deploy for that component.
        public let components: [String: ComponentDeploymentSpecification]?
        /// The time at which the deployment was created, expressed in ISO 8601 format.
        public let creationTimestamp: Date?
        /// The ID of the deployment.
        public let deploymentId: String?
        /// The name of the deployment. You can create deployments without names. If you create a deployment without a name, the AWS IoT Greengrass V2 console shows the deployment name as &lt;targetType&gt;:&lt;targetName&gt;, where targetType and targetName are the type and name of the deployment target.
        public let deploymentName: String?
        /// The deployment policies for the deployment. These policies define how the deployment updates components and handles failure.
        public let deploymentPolicies: DeploymentPolicies?
        /// The status of the deployment.
        public let deploymentStatus: DeploymentStatus?
        /// The ARN of the AWS IoT job that applies the deployment to target devices.
        public let iotJobArn: String?
        /// The job configuration for the deployment configuration. The job configuration specifies the rollout, timeout, and stop configurations for the deployment configuration.
        public let iotJobConfiguration: DeploymentIoTJobConfiguration?
        /// The ID of the AWS IoT job that applies the deployment to target devices.
        public let iotJobId: String?
        /// Whether or not the deployment is the latest revision for its target.
        public let isLatestForTarget: Bool?
        /// The revision number of the deployment.
        public let revisionId: String?
        /// A list of key-value pairs that contain metadata for the resource. For more information, see Tag your resources in the AWS IoT Greengrass V2 Developer Guide.
        public let tags: [String: String]?
        /// The ARN of the target AWS IoT thing or thing group.
        public let targetArn: String?

        public init(components: [String: ComponentDeploymentSpecification]? = nil, creationTimestamp: Date? = nil, deploymentId: String? = nil, deploymentName: String? = nil, deploymentPolicies: DeploymentPolicies? = nil, deploymentStatus: DeploymentStatus? = nil, iotJobArn: String? = nil, iotJobConfiguration: DeploymentIoTJobConfiguration? = nil, iotJobId: String? = nil, isLatestForTarget: Bool? = nil, revisionId: String? = nil, tags: [String: String]? = nil, targetArn: String? = nil) {
            self.components = components
            self.creationTimestamp = creationTimestamp
            self.deploymentId = deploymentId
            self.deploymentName = deploymentName
            self.deploymentPolicies = deploymentPolicies
            self.deploymentStatus = deploymentStatus
            self.iotJobArn = iotJobArn
            self.iotJobConfiguration = iotJobConfiguration
            self.iotJobId = iotJobId
            self.isLatestForTarget = isLatestForTarget
            self.revisionId = revisionId
            self.tags = tags
            self.targetArn = targetArn
        }

        private enum CodingKeys: String, CodingKey {
            case components
            case creationTimestamp
            case deploymentId
            case deploymentName
            case deploymentPolicies
            case deploymentStatus
            case iotJobArn
            case iotJobConfiguration
            case iotJobId
            case isLatestForTarget
            case revisionId
            case tags
            case targetArn
        }
    }

    public struct InstalledComponent: AWSDecodableShape {
        /// The name of the component.
        public let componentName: String?
        /// The version of the component.
        public let componentVersion: String?
        /// Whether or not the component is a root component.
        public let isRoot: Bool?
        /// The lifecycle state of the component.
        public let lifecycleState: InstalledComponentLifecycleState?
        /// The details about the lifecycle state of the component.
        public let lifecycleStateDetails: String?

        public init(componentName: String? = nil, componentVersion: String? = nil, isRoot: Bool? = nil, lifecycleState: InstalledComponentLifecycleState? = nil, lifecycleStateDetails: String? = nil) {
            self.componentName = componentName
            self.componentVersion = componentVersion
            self.isRoot = isRoot
            self.lifecycleState = lifecycleState
            self.lifecycleStateDetails = lifecycleStateDetails
        }

        private enum CodingKeys: String, CodingKey {
            case componentName
            case componentVersion
            case isRoot
            case lifecycleState
            case lifecycleStateDetails
        }
    }

    public struct IoTJobAbortConfig: AWSEncodableShape & AWSDecodableShape {
        /// The list of criteria that define when and how to cancel the configuration deployment.
        public let criteriaList: [IoTJobAbortCriteria]

        public init(criteriaList: [IoTJobAbortCriteria]) {
            self.criteriaList = criteriaList
        }

        public func validate(name: String) throws {
            try self.criteriaList.forEach {
                try $0.validate(name: "\(name).criteriaList[]")
            }
            try self.validate(self.criteriaList, name: "criteriaList", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case criteriaList
        }
    }

    public struct IoTJobAbortCriteria: AWSEncodableShape & AWSDecodableShape {
        /// The action to perform when the criteria are met.
        public let action: IoTJobAbortAction
        /// The type of job deployment failure that can cancel a job.
        public let failureType: IoTJobExecutionFailureType
        /// The minimum number of things that receive the configuration before the job can cancel.
        public let minNumberOfExecutedThings: Int
        /// The minimum percentage of failureType failures that occur before the job can cancel. This parameter supports up to two digits after the decimal (for example, you can specify 10.9 or 10.99, but not 10.999).
        public let thresholdPercentage: Double

        public init(action: IoTJobAbortAction, failureType: IoTJobExecutionFailureType, minNumberOfExecutedThings: Int, thresholdPercentage: Double) {
            self.action = action
            self.failureType = failureType
            self.minNumberOfExecutedThings = minNumberOfExecutedThings
            self.thresholdPercentage = thresholdPercentage
        }

        public func validate(name: String) throws {
            try self.validate(self.minNumberOfExecutedThings, name: "minNumberOfExecutedThings", parent: name, min: 1)
            try self.validate(self.thresholdPercentage, name: "thresholdPercentage", parent: name, max: 100)
        }

        private enum CodingKeys: String, CodingKey {
            case action
            case failureType
            case minNumberOfExecutedThings
            case thresholdPercentage
        }
    }

    public struct IoTJobExecutionsRolloutConfig: AWSEncodableShape & AWSDecodableShape {
        /// The exponential rate to increase the job rollout rate.
        public let exponentialRate: IoTJobExponentialRolloutRate?
        /// The maximum number of devices that receive a pending job notification, per minute.
        public let maximumPerMinute: Int?

        public init(exponentialRate: IoTJobExponentialRolloutRate? = nil, maximumPerMinute: Int? = nil) {
            self.exponentialRate = exponentialRate
            self.maximumPerMinute = maximumPerMinute
        }

        public func validate(name: String) throws {
            try self.exponentialRate?.validate(name: "\(name).exponentialRate")
            try self.validate(self.maximumPerMinute, name: "maximumPerMinute", parent: name, max: 1000)
            try self.validate(self.maximumPerMinute, name: "maximumPerMinute", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case exponentialRate
            case maximumPerMinute
        }
    }

    public struct IoTJobExponentialRolloutRate: AWSEncodableShape & AWSDecodableShape {
        /// The minimum number of devices that receive a pending job notification, per minute, when the job starts. This parameter defines the initial rollout rate of the job.
        public let baseRatePerMinute: Int
        /// The exponential factor to increase the rollout rate for the job. This parameter supports up to one digit after the decimal (for example, you can specify 1.5, but not 1.55).
        public let incrementFactor: Double
        /// The criteria to increase the rollout rate for the job.
        public let rateIncreaseCriteria: IoTJobRateIncreaseCriteria

        public init(baseRatePerMinute: Int, incrementFactor: Double, rateIncreaseCriteria: IoTJobRateIncreaseCriteria) {
            self.baseRatePerMinute = baseRatePerMinute
            self.incrementFactor = incrementFactor
            self.rateIncreaseCriteria = rateIncreaseCriteria
        }

        public func validate(name: String) throws {
            try self.validate(self.baseRatePerMinute, name: "baseRatePerMinute", parent: name, max: 1000)
            try self.validate(self.baseRatePerMinute, name: "baseRatePerMinute", parent: name, min: 1)
            try self.validate(self.incrementFactor, name: "incrementFactor", parent: name, max: 5)
            try self.validate(self.incrementFactor, name: "incrementFactor", parent: name, min: 1)
            try self.rateIncreaseCriteria.validate(name: "\(name).rateIncreaseCriteria")
        }

        private enum CodingKeys: String, CodingKey {
            case baseRatePerMinute
            case incrementFactor
            case rateIncreaseCriteria
        }
    }

    public struct IoTJobRateIncreaseCriteria: AWSEncodableShape & AWSDecodableShape {
        /// The number of devices to receive the job notification before the rollout rate increases.
        public let numberOfNotifiedThings: Int?
        /// The number of devices to successfully run the configuration job before the rollout rate increases.
        public let numberOfSucceededThings: Int?

        public init(numberOfNotifiedThings: Int? = nil, numberOfSucceededThings: Int? = nil) {
            self.numberOfNotifiedThings = numberOfNotifiedThings
            self.numberOfSucceededThings = numberOfSucceededThings
        }

        public func validate(name: String) throws {
            try self.validate(self.numberOfNotifiedThings, name: "numberOfNotifiedThings", parent: name, min: 1)
            try self.validate(self.numberOfSucceededThings, name: "numberOfSucceededThings", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case numberOfNotifiedThings
            case numberOfSucceededThings
        }
    }

    public struct IoTJobTimeoutConfig: AWSEncodableShape & AWSDecodableShape {
        /// The amount of time, in minutes, that devices have to complete the job. The timer starts when the job status is set to IN_PROGRESS. If the job status doesn't change to a terminal state before the time expires, then the job status is set to TIMED_OUT. The timeout interval must be between 1 minute and 7 days (10080 minutes).
        public let inProgressTimeoutInMinutes: Int64?

        public init(inProgressTimeoutInMinutes: Int64? = nil) {
            self.inProgressTimeoutInMinutes = inProgressTimeoutInMinutes
        }

        private enum CodingKeys: String, CodingKey {
            case inProgressTimeoutInMinutes
        }
    }

    public struct LambdaContainerParams: AWSEncodableShape {
        /// The list of system devices that the container can access.
        public let devices: [LambdaDeviceMount]?
        /// The memory size of the container, expressed in kilobytes. Default: 16384 (16 MB)
        public let memorySizeInKB: Int?
        /// Whether or not the container can read information from the device's /sys folder. Default: false
        public let mountROSysfs: Bool?
        /// The list of volumes that the container can access.
        public let volumes: [LambdaVolumeMount]?

        public init(devices: [LambdaDeviceMount]? = nil, memorySizeInKB: Int? = nil, mountROSysfs: Bool? = nil, volumes: [LambdaVolumeMount]? = nil) {
            self.devices = devices
            self.memorySizeInKB = memorySizeInKB
            self.mountROSysfs = mountROSysfs
            self.volumes = volumes
        }

        private enum CodingKeys: String, CodingKey {
            case devices
            case memorySizeInKB
            case mountROSysfs
            case volumes
        }
    }

    public struct LambdaDeviceMount: AWSEncodableShape {
        /// Whether or not to add the component's system user as an owner of the device. Default: false
        public let addGroupOwner: Bool?
        /// The mount path for the device in the file system.
        public let path: String
        /// The permission to access the device: read/only (ro) or read/write (rw). Default: ro
        public let permission: LambdaFilesystemPermission?

        public init(addGroupOwner: Bool? = nil, path: String, permission: LambdaFilesystemPermission? = nil) {
            self.addGroupOwner = addGroupOwner
            self.path = path
            self.permission = permission
        }

        private enum CodingKeys: String, CodingKey {
            case addGroupOwner
            case path
            case permission
        }
    }

    public struct LambdaEventSource: AWSEncodableShape {
        /// The topic to which to subscribe to receive event messages.
        public let topic: String
        /// The type of event source. Choose from the following options:    PUB_SUB – Subscribe to local publish/subscribe messages. This event source type doesn't support MQTT wildcards (+ and #) in the event source topic.    IOT_CORE – Subscribe to AWS IoT Core MQTT messages. This event source type supports MQTT wildcards (+ and #) in the event source topic.
        public let type: LambdaEventSourceType

        public init(topic: String, type: LambdaEventSourceType) {
            self.topic = topic
            self.type = type
        }

        private enum CodingKeys: String, CodingKey {
            case topic
            case type
        }
    }

    public struct LambdaExecutionParameters: AWSEncodableShape {
        /// The map of environment variables that are available to the Lambda function when it runs.
        public let environmentVariables: [String: String]?
        /// The list of event sources to which to subscribe to receive work messages. The Lambda function runs when it receives a message from an event source. You can subscribe this function to local publish/subscribe messages and AWS IoT Core MQTT messages.
        public let eventSources: [LambdaEventSource]?
        /// The list of arguments to pass to the Lambda function when it runs.
        public let execArgs: [String]?
        /// The encoding type that the Lambda function supports. Default: json
        public let inputPayloadEncodingType: LambdaInputPayloadEncodingType?
        /// The parameters for the Linux process that contains the Lambda function.
        public let linuxProcessParams: LambdaLinuxProcessParams?
        /// The maximum amount of time in seconds that a non-pinned Lambda function can idle before the AWS IoT Greengrass Core software stops its process.
        public let maxIdleTimeInSeconds: Int?
        /// The maximum number of instances that a non-pinned Lambda function can run at the same time.
        public let maxInstancesCount: Int?
        /// The maximum size of the message queue for the Lambda function component. The AWS IoT Greengrass core stores messages in a FIFO (first-in-first-out) queue until it can run the Lambda function to consume each message.
        public let maxQueueSize: Int?
        /// Whether or not the Lambda function is pinned, or long-lived.   A pinned Lambda function starts when AWS IoT Greengrass starts and keeps running in its own container.   A non-pinned Lambda function starts only when it receives a work item and exists after it idles for maxIdleTimeInSeconds. If the function has multiple work items, the AWS IoT Greengrass Core software creates multiple instances of the function.   Default: true
        public let pinned: Bool?
        /// The interval in seconds at which a pinned (also known as long-lived) Lambda function component sends status updates to the Lambda manager component.
        public let statusTimeoutInSeconds: Int?
        /// The maximum amount of time in seconds that the Lambda function can process a work item.
        public let timeoutInSeconds: Int?

        public init(environmentVariables: [String: String]? = nil, eventSources: [LambdaEventSource]? = nil, execArgs: [String]? = nil, inputPayloadEncodingType: LambdaInputPayloadEncodingType? = nil, linuxProcessParams: LambdaLinuxProcessParams? = nil, maxIdleTimeInSeconds: Int? = nil, maxInstancesCount: Int? = nil, maxQueueSize: Int? = nil, pinned: Bool? = nil, statusTimeoutInSeconds: Int? = nil, timeoutInSeconds: Int? = nil) {
            self.environmentVariables = environmentVariables
            self.eventSources = eventSources
            self.execArgs = execArgs
            self.inputPayloadEncodingType = inputPayloadEncodingType
            self.linuxProcessParams = linuxProcessParams
            self.maxIdleTimeInSeconds = maxIdleTimeInSeconds
            self.maxInstancesCount = maxInstancesCount
            self.maxQueueSize = maxQueueSize
            self.pinned = pinned
            self.statusTimeoutInSeconds = statusTimeoutInSeconds
            self.timeoutInSeconds = timeoutInSeconds
        }

        public func validate(name: String) throws {
            try self.environmentVariables?.forEach {
                try validate($0.key, name: "environmentVariables.key", parent: name, min: 1)
            }
        }

        private enum CodingKeys: String, CodingKey {
            case environmentVariables
            case eventSources
            case execArgs
            case inputPayloadEncodingType
            case linuxProcessParams
            case maxIdleTimeInSeconds
            case maxInstancesCount
            case maxQueueSize
            case pinned
            case statusTimeoutInSeconds
            case timeoutInSeconds
        }
    }

    public struct LambdaFunctionRecipeSource: AWSEncodableShape {
        /// The component versions on which this Lambda function component depends.
        public let componentDependencies: [String: ComponentDependencyRequirement]?
        /// The system and runtime parameters for the Lambda function as it runs on the AWS IoT Greengrass core device.
        public let componentLambdaParameters: LambdaExecutionParameters?
        /// The name of the component. Defaults to the name of the Lambda function.
        public let componentName: String?
        /// The platforms that the component version supports.
        public let componentPlatforms: [ComponentPlatform]?
        /// The version of the component. Defaults to the version of the Lambda function as a semantic version. For example, if your function version is 3, the component version becomes 3.0.0.
        public let componentVersion: String?
        /// The ARN of the Lambda function. The ARN must include the version of the function to import. You can't use version aliases like $LATEST.
        public let lambdaArn: String

        public init(componentDependencies: [String: ComponentDependencyRequirement]? = nil, componentLambdaParameters: LambdaExecutionParameters? = nil, componentName: String? = nil, componentPlatforms: [ComponentPlatform]? = nil, componentVersion: String? = nil, lambdaArn: String) {
            self.componentDependencies = componentDependencies
            self.componentLambdaParameters = componentLambdaParameters
            self.componentName = componentName
            self.componentPlatforms = componentPlatforms
            self.componentVersion = componentVersion
            self.lambdaArn = lambdaArn
        }

        public func validate(name: String) throws {
            try self.componentDependencies?.forEach {
                try validate($0.key, name: "componentDependencies.key", parent: name, min: 1)
                try $0.value.validate(name: "\(name).componentDependencies[\"\($0.key)\"]")
            }
            try self.componentLambdaParameters?.validate(name: "\(name).componentLambdaParameters")
            try self.validate(self.componentName, name: "componentName", parent: name, max: 128)
            try self.validate(self.componentName, name: "componentName", parent: name, min: 1)
            try self.validate(self.componentName, name: "componentName", parent: name, pattern: "[a-zA-Z0-9-_.]+")
            try self.componentPlatforms?.forEach {
                try $0.validate(name: "\(name).componentPlatforms[]")
            }
            try self.validate(self.componentVersion, name: "componentVersion", parent: name, max: 64)
            try self.validate(self.componentVersion, name: "componentVersion", parent: name, min: 1)
            try self.validate(self.componentVersion, name: "componentVersion", parent: name, pattern: "[0-9a-zA-Z-.+]+")
            try self.validate(self.lambdaArn, name: "lambdaArn", parent: name, pattern: "arn:aws(-cn|-us-gov)?:lambda:[^:]+:[0-9]+:function:[a-zA-Z0-9-_]+:[0-9]+")
        }

        private enum CodingKeys: String, CodingKey {
            case componentDependencies
            case componentLambdaParameters
            case componentName
            case componentPlatforms
            case componentVersion
            case lambdaArn
        }
    }

    public struct LambdaLinuxProcessParams: AWSEncodableShape {
        /// The parameters for the container in which the Lambda function runs.
        public let containerParams: LambdaContainerParams?
        /// The isolation mode for the process that contains the Lambda function. The process can run in an isolated runtime environment inside the AWS IoT Greengrass container, or as a regular process outside any container. Default: GreengrassContainer
        public let isolationMode: LambdaIsolationMode?

        public init(containerParams: LambdaContainerParams? = nil, isolationMode: LambdaIsolationMode? = nil) {
            self.containerParams = containerParams
            self.isolationMode = isolationMode
        }

        private enum CodingKeys: String, CodingKey {
            case containerParams
            case isolationMode
        }
    }

    public struct LambdaVolumeMount: AWSEncodableShape {
        /// Whether or not to add the AWS IoT Greengrass user group as an owner of the volume. Default: false
        public let addGroupOwner: Bool?
        /// The path to the logical volume in the file system.
        public let destinationPath: String
        /// The permission to access the volume: read/only (ro) or read/write (rw). Default: ro
        public let permission: LambdaFilesystemPermission?
        /// The path to the physical volume in the file system.
        public let sourcePath: String

        public init(addGroupOwner: Bool? = nil, destinationPath: String, permission: LambdaFilesystemPermission? = nil, sourcePath: String) {
            self.addGroupOwner = addGroupOwner
            self.destinationPath = destinationPath
            self.permission = permission
            self.sourcePath = sourcePath
        }

        private enum CodingKeys: String, CodingKey {
            case addGroupOwner
            case destinationPath
            case permission
            case sourcePath
        }
    }

    public struct ListComponentVersionsRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "arn", location: .uri(locationName: "arn")),
            AWSMemberEncoding(label: "maxResults", location: .querystring(locationName: "maxResults")),
            AWSMemberEncoding(label: "nextToken", location: .querystring(locationName: "nextToken"))
        ]

        /// The ARN of the component version.
        public let arn: String
        /// The maximum number of results to be returned per paginated request.
        public let maxResults: Int?
        /// The token to be used for the next set of paginated results.
        public let nextToken: String?

        public init(arn: String, maxResults: Int? = nil, nextToken: String? = nil) {
            self.arn = arn
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.arn, name: "arn", parent: name, pattern: "arn:aws(-cn|-us-gov)?:greengrass:[^:]+:(aws|[0-9]+):components:[^:]+")
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListComponentVersionsResponse: AWSDecodableShape {
        /// A list of versions that exist for the component.
        public let componentVersions: [ComponentVersionListItem]?
        /// The token for the next set of results, or null if there are no additional results.
        public let nextToken: String?

        public init(componentVersions: [ComponentVersionListItem]? = nil, nextToken: String? = nil) {
            self.componentVersions = componentVersions
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case componentVersions
            case nextToken
        }
    }

    public struct ListComponentsRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "maxResults", location: .querystring(locationName: "maxResults")),
            AWSMemberEncoding(label: "nextToken", location: .querystring(locationName: "nextToken")),
            AWSMemberEncoding(label: "scope", location: .querystring(locationName: "scope"))
        ]

        /// The maximum number of results to be returned per paginated request.
        public let maxResults: Int?
        /// The token to be used for the next set of paginated results.
        public let nextToken: String?
        /// The scope of the components to list. Default: PRIVATE
        public let scope: ComponentVisibilityScope?

        public init(maxResults: Int? = nil, nextToken: String? = nil, scope: ComponentVisibilityScope? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.scope = scope
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListComponentsResponse: AWSDecodableShape {
        /// A list that summarizes each component.
        public let components: [Component]?
        /// The token for the next set of results, or null if there are no additional results.
        public let nextToken: String?

        public init(components: [Component]? = nil, nextToken: String? = nil) {
            self.components = components
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case components
            case nextToken
        }
    }

    public struct ListCoreDevicesRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "maxResults", location: .querystring(locationName: "maxResults")),
            AWSMemberEncoding(label: "nextToken", location: .querystring(locationName: "nextToken")),
            AWSMemberEncoding(label: "status", location: .querystring(locationName: "status")),
            AWSMemberEncoding(label: "thingGroupArn", location: .querystring(locationName: "thingGroupArn"))
        ]

        /// The maximum number of results to be returned per paginated request.
        public let maxResults: Int?
        /// The token to be used for the next set of paginated results.
        public let nextToken: String?
        /// The core device status by which to filter. If you specify this parameter, the list includes only core devices that have this status. Choose one of the following options:    HEALTHY – The AWS IoT Greengrass Core software and all components run on the core device without issue.    UNHEALTHY – The AWS IoT Greengrass Core software or a component is in a failed state on the core device.
        public let status: CoreDeviceStatus?
        /// The ARN of the AWS IoT thing group by which to filter. If you specify this parameter, the list includes only core devices that are members of this thing group.
        public let thingGroupArn: String?

        public init(maxResults: Int? = nil, nextToken: String? = nil, status: CoreDeviceStatus? = nil, thingGroupArn: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.status = status
            self.thingGroupArn = thingGroupArn
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.thingGroupArn, name: "thingGroupArn", parent: name, pattern: "arn:aws(-cn|-us-gov)?:iot:[^:]+:[0-9]+:thinggroup/.+")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListCoreDevicesResponse: AWSDecodableShape {
        /// A list that summarizes each core device.
        public let coreDevices: [CoreDevice]?
        /// The token for the next set of results, or null if there are no additional results.
        public let nextToken: String?

        public init(coreDevices: [CoreDevice]? = nil, nextToken: String? = nil) {
            self.coreDevices = coreDevices
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case coreDevices
            case nextToken
        }
    }

    public struct ListDeploymentsRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "historyFilter", location: .querystring(locationName: "historyFilter")),
            AWSMemberEncoding(label: "maxResults", location: .querystring(locationName: "maxResults")),
            AWSMemberEncoding(label: "nextToken", location: .querystring(locationName: "nextToken")),
            AWSMemberEncoding(label: "targetArn", location: .querystring(locationName: "targetArn"))
        ]

        /// The filter for the list of deployments. Choose one of the following options:    ALL – The list includes all deployments.    LATEST_ONLY – The list includes only the latest revision of each deployment.   Default: LATEST_ONLY
        public let historyFilter: DeploymentHistoryFilter?
        /// The maximum number of results to be returned per paginated request.
        public let maxResults: Int?
        /// The token to be used for the next set of paginated results.
        public let nextToken: String?
        /// The ARN of the target AWS IoT thing or thing group.
        public let targetArn: String?

        public init(historyFilter: DeploymentHistoryFilter? = nil, maxResults: Int? = nil, nextToken: String? = nil, targetArn: String? = nil) {
            self.historyFilter = historyFilter
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.targetArn = targetArn
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.targetArn, name: "targetArn", parent: name, pattern: "arn:aws(-cn|-us-gov)?:iot:[^:]+:[0-9]+:(thing|thinggroup)/.+")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListDeploymentsResponse: AWSDecodableShape {
        /// A list that summarizes each deployment.
        public let deployments: [Deployment]?
        /// The token for the next set of results, or null if there are no additional results.
        public let nextToken: String?

        public init(deployments: [Deployment]? = nil, nextToken: String? = nil) {
            self.deployments = deployments
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case deployments
            case nextToken
        }
    }

    public struct ListEffectiveDeploymentsRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "coreDeviceThingName", location: .uri(locationName: "coreDeviceThingName")),
            AWSMemberEncoding(label: "maxResults", location: .querystring(locationName: "maxResults")),
            AWSMemberEncoding(label: "nextToken", location: .querystring(locationName: "nextToken"))
        ]

        /// The name of the core device. This is also the name of the AWS IoT thing.
        public let coreDeviceThingName: String
        /// The maximum number of results to be returned per paginated request.
        public let maxResults: Int?
        /// The token to be used for the next set of paginated results.
        public let nextToken: String?

        public init(coreDeviceThingName: String, maxResults: Int? = nil, nextToken: String? = nil) {
            self.coreDeviceThingName = coreDeviceThingName
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.coreDeviceThingName, name: "coreDeviceThingName", parent: name, max: 128)
            try self.validate(self.coreDeviceThingName, name: "coreDeviceThingName", parent: name, min: 1)
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListEffectiveDeploymentsResponse: AWSDecodableShape {
        /// A list that summarizes each deployment on the core device.
        public let effectiveDeployments: [EffectiveDeployment]?
        /// The token for the next set of results, or null if there are no additional results.
        public let nextToken: String?

        public init(effectiveDeployments: [EffectiveDeployment]? = nil, nextToken: String? = nil) {
            self.effectiveDeployments = effectiveDeployments
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case effectiveDeployments
            case nextToken
        }
    }

    public struct ListInstalledComponentsRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "coreDeviceThingName", location: .uri(locationName: "coreDeviceThingName")),
            AWSMemberEncoding(label: "maxResults", location: .querystring(locationName: "maxResults")),
            AWSMemberEncoding(label: "nextToken", location: .querystring(locationName: "nextToken"))
        ]

        /// The name of the core device. This is also the name of the AWS IoT thing.
        public let coreDeviceThingName: String
        /// The maximum number of results to be returned per paginated request.
        public let maxResults: Int?
        /// The token to be used for the next set of paginated results.
        public let nextToken: String?

        public init(coreDeviceThingName: String, maxResults: Int? = nil, nextToken: String? = nil) {
            self.coreDeviceThingName = coreDeviceThingName
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.coreDeviceThingName, name: "coreDeviceThingName", parent: name, max: 128)
            try self.validate(self.coreDeviceThingName, name: "coreDeviceThingName", parent: name, min: 1)
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListInstalledComponentsResponse: AWSDecodableShape {
        /// A list that summarizes each component on the core device.
        public let installedComponents: [InstalledComponent]?
        /// The token for the next set of results, or null if there are no additional results.
        public let nextToken: String?

        public init(installedComponents: [InstalledComponent]? = nil, nextToken: String? = nil) {
            self.installedComponents = installedComponents
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case installedComponents
            case nextToken
        }
    }

    public struct ListTagsForResourceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri(locationName: "resourceArn"))
        ]

        /// The ARN of the resource.
        public let resourceArn: String

        public init(resourceArn: String) {
            self.resourceArn = resourceArn
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "arn:aws(-cn|-us-gov)?:greengrass:[^:]+:(aws|[0-9]+):(components|deployments|coreDevices):.+")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListTagsForResourceResponse: AWSDecodableShape {
        /// A list of key-value pairs that contain metadata for the resource. For more information, see Tag your resources in the AWS IoT Greengrass V2 Developer Guide.
        public let tags: [String: String]?

        public init(tags: [String: String]? = nil) {
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case tags
        }
    }

    public struct ResolveComponentCandidatesRequest: AWSEncodableShape {
        /// The list of components to resolve.
        public let componentCandidates: [ComponentCandidate]
        /// The platform to use to resolve compatible components.
        public let platform: ComponentPlatform

        public init(componentCandidates: [ComponentCandidate], platform: ComponentPlatform) {
            self.componentCandidates = componentCandidates
            self.platform = platform
        }

        public func validate(name: String) throws {
            try self.componentCandidates.forEach {
                try $0.validate(name: "\(name).componentCandidates[]")
            }
            try self.platform.validate(name: "\(name).platform")
        }

        private enum CodingKeys: String, CodingKey {
            case componentCandidates
            case platform
        }
    }

    public struct ResolveComponentCandidatesResponse: AWSDecodableShape {
        /// A list of components that meet the requirements that you specify in the request. This list includes each component's recipe that you can use to install the component.
        public let resolvedComponentVersions: [ResolvedComponentVersion]?

        public init(resolvedComponentVersions: [ResolvedComponentVersion]? = nil) {
            self.resolvedComponentVersions = resolvedComponentVersions
        }

        private enum CodingKeys: String, CodingKey {
            case resolvedComponentVersions
        }
    }

    public struct ResolvedComponentVersion: AWSDecodableShape {
        /// The ARN of the component version.
        public let arn: String?
        /// The name of the component.
        public let componentName: String?
        /// The version of the component.
        public let componentVersion: String?
        /// The recipe of the component version.
        public let recipe: Data?

        public init(arn: String? = nil, componentName: String? = nil, componentVersion: String? = nil, recipe: Data? = nil) {
            self.arn = arn
            self.componentName = componentName
            self.componentVersion = componentVersion
            self.recipe = recipe
        }

        private enum CodingKeys: String, CodingKey {
            case arn
            case componentName
            case componentVersion
            case recipe
        }
    }

    public struct TagResourceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri(locationName: "resourceArn"))
        ]

        /// The ARN of the resource to tag.
        public let resourceArn: String
        /// A list of key-value pairs that contain metadata for the resource. For more information, see Tag your resources in the AWS IoT Greengrass V2 Developer Guide.
        public let tags: [String: String]

        public init(resourceArn: String, tags: [String: String]) {
            self.resourceArn = resourceArn
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "arn:aws(-cn|-us-gov)?:greengrass:[^:]+:(aws|[0-9]+):(components|deployments|coreDevices):.+")
            try self.tags.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.key, name: "tags.key", parent: name, pattern: "^(?!aws:)[a-zA-Z+-=._:/]+$")
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
        }

        private enum CodingKeys: String, CodingKey {
            case tags
        }
    }

    public struct TagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct UntagResourceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri(locationName: "resourceArn")),
            AWSMemberEncoding(label: "tagKeys", location: .querystring(locationName: "tagKeys"))
        ]

        /// The ARN of the resource to untag.
        public let resourceArn: String
        /// A list of keys for tags to remove from the resource.
        public let tagKeys: [String]

        public init(resourceArn: String, tagKeys: [String]) {
            self.resourceArn = resourceArn
            self.tagKeys = tagKeys
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "arn:aws(-cn|-us-gov)?:greengrass:[^:]+:(aws|[0-9]+):(components|deployments|coreDevices):.+")
            try self.tagKeys.forEach {
                try validate($0, name: "tagKeys[]", parent: name, max: 128)
                try validate($0, name: "tagKeys[]", parent: name, min: 1)
                try validate($0, name: "tagKeys[]", parent: name, pattern: "^(?!aws:)[a-zA-Z+-=._:/]+$")
            }
            try self.validate(self.tagKeys, name: "tagKeys", parent: name, max: 50)
            try self.validate(self.tagKeys, name: "tagKeys", parent: name, min: 1)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct UntagResourceResponse: AWSDecodableShape {
        public init() {}
    }
}
